#!/usr/bin/python3
# -*- coding: utf-8 -*-

import os
import re
from typing import Any, Dict

import allure
from playwright.sync_api import Page, expect

from models.base_page import BasePage
from public.project_patch import DOWNLOAD_DIR
from utils.log import log


class SecurityGroupDetailPage(BasePage):
    def __init__(self, page: Page):
        super().__init__(page)
        self.route = "security_groups/security_groups"

    @allure.step("点击详情页-基本属性扩展按钮")
    def click_detail_page_expand_button(self) -> None:
        """
        点击详情页-基本属性扩展按钮
        :return:
        """
        self.locator(".dropdown-toggle").first.click()

    def click_detail_page_expand_button_operation(self, operation: str = "") -> None:
        """
        根据关键字，点击对应的操作按钮
        :param operation: 执行 修改、应用安全组规则、绑定标签、添加到项目、从项目中移除、删除 等操作
        :return:
        """
        with allure.step(f"点击详情页-基本属性扩展菜单下的->{operation} 按钮"):
            self.locator("a").filter(has_text=f"{operation}").first.click()

    @allure.step("点击添加安全组规则")
    def click_add_security_group_rule_button(self) -> None:
        """
        点击添加安全组规则
        :return:
        """
        self.locator("a").filter(has_text="添加规则").click()

    @allure.step("输入安全组规则名称")
    def fill_sg_rule_name(self, rule_name="") -> None:
        """
        输入安全组规则名称
        :param rule_name: 名称 可为空
        :return:
        """
        self.fill('input[name="security_group_rule_name"]', rule_name)

    @allure.step("输入优先级")
    def fill_priority(self, priority: int = 0) -> None:
        """
        输入优先级
        :param priority: 有效值 0-100
        :return:
        """
        self.fill('input[name="priority"]', str(priority))

    @allure.step("选择方向")
    def select_direction(self, value: int = 0) -> None:
        """
        选择方向
        :param value: 方向0: 下行、1:上行
        :return:
        """
        self.select.select_option(select_option='select[name="direction"]', value=value)

    @allure.step("选择行为")
    def select_action(self, value: str = "accept") -> None:
        """
        选择行为
        :param value:  accept:同意、drop:拒绝
        :return:
        """
        self.select.select_option(select_option='select[name="action"]', value=value)

    @allure.step("选择协议")
    def select_protocol(self, value: str = "tcp") -> None:
        """
        选择协议
        :param value: tcp、udp、icmp 等等
        :return:
        """
        self.select.select_option(select_option='select[name="protocol"]', value=value)

    @allure.step("选择ICMP类型")
    def select_icmp_type(self, value: str = "ALL") -> None:
        """
        选择icmp类型
        :param value: 默认 ALL
        :return:
        """
        self.select.select_option(select_option='select[name="val1"]', value=value)

    @allure.step("选择ICMP代码")
    def select_icmp_code(self, value: str = "ALL") -> None:
        self.select.select_option(select_option='select[name="val2"]', value=value)

    @allure.step("输入起始端口")
    def fill_start_port(self, port: int = "") -> None:
        """
        输入起始端口
        :param port:
        :return:
        """
        self.fill('input[name="val1"]', port)

    @allure.step("输入结束端口")
    def fill_end_port(self, port: int = "") -> None:
        """
        输入结束端口
        :param port:
        :return:
        """
        self.fill('input[name="val2"]', port)

    @allure.step("输入源ip")
    def fill_source_ip(self, source_ip: str = "") -> None:
        """
        输入源ip
        :param source_ip: ip地址 192.168.9.1/24 或 fe80::5054:a8ff:fe81:a71e/64 等，不填表示所有IP地址
        :return:
        """
        self.fill('input[name="val3"]', source_ip)

    @allure.step("点击提交按钮")
    def click_submit_button(self) -> None:
        """点击提交按钮"""
        self.popout.click_submit_by_role_button()

    @allure.step("点击应用修改按钮")
    def click_apply_button(self) -> None:
        """点击应用修改按钮"""
        self.locator("a").filter(has_text="应用修改").click()

    @allure.step("获取应用更新时的提示框")
    def get_alert_text_content(self) -> str:
        """获取应用更新时的提示框文本"""
        alert_text_content = self.popout.get_alert_text_content()
        return alert_text_content

    @allure.step("点击更多操作按钮")
    def click_more_operation_button(self) -> None:
        """点击更多操作按钮"""
        self.locator("div").filter(has_text=re.compile(r"^更多操作导入规则导出规则$")).get_by_role(
            "textbox"
        ).click()

    @allure.step("点击导入规则按钮")
    def click_import_role_button(self) -> None:
        """点击导入规则按钮"""
        self.locator("a").filter(has_text="导入规则").click()

    @allure.step("点击导出规则按钮")
    def click_export_role_button(self) -> Dict[str, str]:
        """点击导出规则按钮"""
        with self.page.expect_download() as download_info:
            self.locator("a").filter(has_text="导出规则").click()
        download = download_info.value
        file_name = download.suggested_filename
        download_path = DOWNLOAD_DIR / file_name
        if download_path.exists():
            log.info(f"文件已存在, 删除旧文件: {download_path}")
            download_path.unlink()
        log.info(f"文件不存在, 创建新文件: {download_path}")
        download.save_as(download_path)
        # file_path = download.path()
        try:
            file_size = download.response().headers.get("Content-Length")
        except Exception as e:
            log.warning(f"获取文件大小时发生错误: {e}")
            file_size = "未知"
        log.info(f"文件名: {file_name}")
        log.info(f"文件大小: {file_size} bytes")
        log.info(f"文件路径: {download_path}")
        return {
            "file_path": download_path,
            "file_name": file_name,
            "file_size": file_size,
        }

    @allure.step("点击导入文件按钮")
    def click_import_file_button(self, file_path: str) -> tuple:
        """点击导入文件按钮"""
        response_count = 0
        second_response_data = None

        def handle_response(response):
            """
            监听网络请求过滤第二次 ImportSecurityGroupRules Action 请求
            :param response:
            :return:
            """
            nonlocal response_count, second_response_data
            if "/api/?action=ImportSecurityGroupRules" in response.url and response_count < 5:
                log.debug(f"请求次数: {response_count}")
                log.debug(f"响应URL: {response.url}")
                log.debug(f"响应:{response.json()}")
                response_count += 1
                if response_count == 1:
                    second_response_data = response.json()

        with self.page.expect_file_chooser() as fc_info:
            self.page.get_by_text("上传文件").click()
        file_chooser = fc_info.value
        file_chooser.set_files(file_path)

        self.page.on("response", handle_response)
        self.page.get_by_role("button", name="导入").click()
        self.page.wait_for_timeout(3000)
        self.page.remove_listener("response", handle_response)

        assert second_response_data is not None, "未成功捕获第二次请求的响应"
        security_group = second_response_data["security_group"]
        security_group_rules = second_response_data["security_group_rules"]
        log.info(f"安全组:{security_group} 添加的规则id列表为: {security_group_rules}")
        return security_group, security_group_rules
